#pragma ident "$Id: SolverIFCBMixed.hpp 2648 2011-06-09 08:01:41Z shjzhang $"

/**
 * @file SolverIFCBMixed.hpp
 * General Solver.
 */

#ifndef GPSTK_SolverIFCBMixed_HPP
#define GPSTK_SolverIFCBMixed_HPP

//============================================================================
//
//  Revision
//
//  2019/08/13  
//  solve the ifcb using ppp method
//  shjzhang    
//
//============================================================================


#include "SolverBase.hpp"
#include "TypeID.hpp"
#include "ProcessingClass.hpp"
#include "EquationSystem.hpp"
#include "StochasticModel.hpp"
#include "SimpleKalmanFilter.hpp"


namespace gpstk
{

      /** @addtogroup GPSsolutions */
      /// @ingroup math

      //@{

      // type definition for usage in other program
   typedef std::map<CommonTime, VariableDataMap > epochVarDataMap;
   typedef std::map<CommonTime, CovarianceDataMap > epochCovDataMap;
   typedef std::map<CommonTime, sourceTypeValueMap> epochSrcDataMap;
   typedef std::map<Variable, int> VariableIntMap;


   class SolverIFCBMixed : public SolverBase
   {
   public:

      SolverIFCBMixed()
          : firstTime(true), print(false)
      {
         Init();
      }

      virtual sourceTypeValueMap& Process(CommonTime& epoch,
                                          const SatID& sat, 
                                          sourceTypeValueMap& srcTypeValueData);

         /// Returns an index identifying this object.
      virtual void Init(void) ;

         /// Returns an index identifying this object.
      virtual void setUpEquations(void) ;

      double smoothAmb( const SourceID& source,
                        bool csOcurred,
                        const double& amb );


      void printOut(std::string file);

      void setMW25File(std::string file)
      {
          obsStreamMW25.open(file);
      };

      void setGFIFFile(std::string file)
      {
          obsStreamGFIF.open(file);
      };

      void printMW25( const CommonTime& epoch, SourceIDSet sourceSet,
                      sourceTypeValueMap& srcTypeValueData)
      {
          YDSTime time( epoch );
          obsStreamMW25 << time.year << " " << time.doy  << " " << time.sod <<  " ";
          for(SourceIDSet::iterator srcIt=sourceSet.begin();
                  srcIt!=sourceSet.end();
                  srcIt++)
          {
              double mw25(0.0);
              double gfif(0.0);
              if(srcTypeValueData.find((*srcIt))!=srcTypeValueData.end()) 
              {
                  mw25 = srcTypeValueData[(*srcIt)][TypeID::MW25Frac];
                  gfif = srcTypeValueData[(*srcIt)][TypeID::GFIFFrac];
              }
              obsStreamMW25 << setprecision(6) << fixed<< setw(10) ;
              obsStreamMW25 << mw25 << " " ;
          }
          obsStreamMW25<< endl;
      };

      void printGFIF( const CommonTime& epoch, SourceIDSet sourceSet,
                      sourceTypeValueMap& srcTypeValueData)
      {
          YDSTime time( epoch );
          (obsStreamGFIF) << time.year << " " << time.doy  << " " << time.sod <<  " ";
          for(SourceIDSet::iterator srcIt=sourceSet.begin();
                  srcIt!=sourceSet.end();
                  srcIt++)
          {
              double gfif(0.0);
              if(srcTypeValueData.find((*srcIt))!=srcTypeValueData.end()) 
              {
                  gfif = srcTypeValueData[(*srcIt)][TypeID::GFIFFrac];
              }
              obsStreamGFIF << setprecision(6) << setw(10) << fixed;
              obsStreamGFIF << gfif << " ";
          }
          obsStreamGFIF<< endl;
      };

      std::map<CommonTime, double> getEpochIFCBData()
      {
          return epochDiffIFCBData;
      };

      virtual double getIFCBDiff()
      {
          return ifcbDiff;
      };

      virtual double getIFCBUndiff()
      {
          return ifcbUndiff;
      };

         /// Returns an index identifying this object.
      virtual int getIndex(void) const;

         /// Returns a string identifying this object.
      virtual std::string getClassName(void) const;

         /// Destructor.
      virtual ~SolverIFCBMixed() {};


   protected:

      /// Boolean indicating if this filter was run at least once
      bool firstTime;

      SatID currSat;

      VariableSet oldUnknowns;
      bool print;

      double bg15;

         /// Boolean indicating if this filter was run at least once
      double resetInterval;
      /// diffIFCB
      double ifcbDiff;

      double ifcbUndiff;

      std::ofstream ifcbStream;
      std::ofstream obsStreamMW25;
      std::ofstream obsStreamGFIF;

      sourceTypeValueMap lastSrcData;
      std::map<SourceID, double> srcArcData;
      std::map<CommonTime, double> epochDiffIFCBData;
      std::map<CommonTime, double> epochUndiffIFCBData;

      std::map<SourceID, bool> sourceCSData;
      std::map<SourceID, double> sourceGFIFData;

      /// A structure used to store filter data for a SV.
      struct filterData
      {
          // Default constructor initializing the data in the structure
          filterData() 
              : windowSize(0), meanAmb(0.0), varAmb(100.0)
          {};
          int windowSize;         ///< Size of current window, in samples.
          double meanAmb;          ///< Accumulated mean value of combination.
          double varAmb;           ///< Accumulated std value of combination.
      };

      typedef std::map<SourceID, filterData> AmbData;

      /// Map holding the information regarding every satellite
      AmbData ambData;


   private:


         /// Initial index assigned to this class.
      static int classIndex;

         /// Index belonging to this object.
      int index;

         /// Sets the index and increment classIndex.
      void setIndex(void)
      { index = classIndex++; };


   }; // End of class 'SolverIFCBMixed'


      //@}

}  // End of namespace gpstk
#endif   // GPSTK_SolverIFCBMixed_HPP
